/*****************************************************************************************
   
   Copyright (c) Microsoft Corporation. All rights reserved.

   Use of this code sample is subject to the terms of the Microsoft
   Permissive License, a copy of which should always be distributed with
   this file.  You can also access a copy of this license agreement at:
   http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx

 ****************************************************************************************/

using System;

namespace GrooveWebServicesV12Helpers
{
	/// <summary>
	/// Interfaces to a Groove contact directory (for example, an enterprise's management server).
	/// </summary>
	public class ContactDirectory :
		GrooveWebServicesV12Helpers.Shared.IGrooveWebServicesEventCallback
	{
		private GrooveWebServicesV12Helpers.Account m_Account;
		private GrooveWebServicesV12Helpers.Contact[] m_FetchedContacts;
		private GrooveWebServicesV12Helpers.ContactSummary[] m_SearchedContactSummaries;

		private GrooveContactsWebService.ContactDirectory m_ContactDirectory;

		private const int DEFAULT_TIME_TO_LIVE_IN_HOURS = 1;
		private const int DEFAULT_TIME_TO_WAIT_IN_SECONDS = 60;

		private bool m_WaitingForEvent;

		public ContactDirectory(GrooveWebServicesV12Helpers.Account i_Account, GrooveContactsWebService.ContactDirectory i_ContactDirectory)
		{
			m_Account = i_Account;
			m_ContactDirectory = i_ContactDirectory;
		}

		#region ContactDirectory Properties And Methods

		/// <summary>
		/// The Account which has access to this ContactDirectory
		/// </summary>
		public GrooveWebServicesV12Helpers.Account Account
		{
			get
			{
				return m_Account;
			}
		}

		/// <summary>
		/// The ID of this ContactDirectory
		/// </summary>
		public string ID
		{
			get
			{
				return m_ContactDirectory.ID;
			}
		}

		/// <summary>
		/// The name of this ContactDirectory
		/// </summary>
		public string Name
		{
			get
			{
				return m_ContactDirectory.Name;
			}
		}

		/// <summary>
		/// Searches this ContactDirectory for contacts matching the query string.
		/// NOTE: This method pumps messages (System.Windows.Forms.Application.DoEvents)
		/// </summary>
		/// <param name="i_Query">(Partial) name or email address</param>
		/// <returns>Array of ContactSummary.</returns>
		public GrooveWebServicesV12Helpers.ContactSummary[] Search(string i_Query)
		{
			return this.Search
				(
				i_Query,
				DEFAULT_TIME_TO_WAIT_IN_SECONDS
				);
		}

		/// <summary>
		/// Searches this ContactDirectory for contacts matching the query string.
		/// NOTE: This method pumps messages (System.Windows.Forms.Application.DoEvents)
		/// </summary>
		/// <param name="i_Query">(Partial) name or email address</param>
		/// <param name="i_TimeToWaitInSeconds">Time to wait, in seconds, before aborting the search.</param>
		/// <returns>Array of ContactSummary.</returns>
		public GrooveWebServicesV12Helpers.ContactSummary[] Search (string i_Query, int i_TimeToWaitInSeconds)
		{
			//  ---------------------------------------------------------------------------------------------
			//  BIG HONKING NOTE:  This method pumps messages while waiting for result from web service, thus
			//                     allowing for reentrancy.
			//  ---------------------------------------------------------------------------------------------
			
			//  Reset member variable
			m_SearchedContactSummaries = null;

			//  Get initialized reference to web service
			GrooveContactsWebService.GrooveContacts ContactsWebService = GrooveWebServicesV12Helpers.Contact.CreateInitializedContactsWebService
				(
				m_Account.IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_CONTACTS_URI,
				m_Account.Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to search contacts
			string SubscriptionID = ContactsWebService.Search
				(
				GrooveWebServicesV12Helpers.EventManager.s_EventURI,
				DEFAULT_TIME_TO_LIVE_IN_HOURS,
				i_Query,
				this.ID
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("ContactsWebService::Search, " + TimeSpan.TotalMilliseconds + " ms");
			}

			//  Subscribe for the one event we should get back
			GrooveWebServicesV12Helpers.EventManager.AddEventListener
				(
				m_Account.Context,
				m_Account.IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_CONTACT_DIRECTORY_EVENT_CLASS,
				"",			// Source URI
				GrooveWebServicesV12Helpers.EventManager.s_EventURI,
				SubscriptionID,
				1,		// 1 hour time to live
				this
				);

			//  Set flag
			m_WaitingForEvent = true;

			try
			{
				BeginDateTime = System.DateTime.Now.AddSeconds(i_TimeToWaitInSeconds);
				while (m_WaitingForEvent && (BeginDateTime > System.DateTime.Now))
				{
					System.Windows.Forms.Application.DoEvents();
					System.Threading.Thread.Sleep(100);
				}

				//  Reset flag
				m_WaitingForEvent = false;
			}
			finally
			{
				//  Unsubscribe for events
				GrooveWebServicesV12Helpers.EventManager.RemoveEventListener
					(
					SubscriptionID,
					this
					);
			}

			return m_SearchedContactSummaries;
		}

		/// <summary>
		/// Fetches a contact from the ContactDirectory to the local contact store.
		/// NOTE: This method pumps messages (System.Windows.Forms.Application.DoEvents)
		/// </summary>
		/// <param name="i_ContactURI">The ContactURI</param>
		/// <returns>The Contact, if successful.</returns>
		public GrooveWebServicesV12Helpers.Contact Fetch(string i_ContactURI)
		{
			string[] ContactURIs = new string[1]{i_ContactURI};
			GrooveWebServicesV12Helpers.Contact[] Contacts = this.Fetch
				(
				ContactURIs,
				DEFAULT_TIME_TO_WAIT_IN_SECONDS
				);

			if ((Contacts != null) && (Contacts.Length > 0))
				return Contacts[0];

			return null;
		}

		/// <summary>
		/// Fetches contacts from the ContactDirectory to the local contact store.
		/// </summary>
		/// <param name="i_ContactURIs">Array of ContactURIs</param>
		/// <returns>Array of contacts, if successful.</returns>
		public GrooveWebServicesV12Helpers.Contact[] Fetch(string[] i_ContactURIs)
		{
			return this.Fetch
				(
				i_ContactURIs,
				DEFAULT_TIME_TO_WAIT_IN_SECONDS
				);
		}

		/// <summary>
		/// Fetches contacts from the ContactDirectory to the local contact store.
		/// NOTE: This method pumps messages (System.Windows.Forms.Application.DoEvents)
		/// </summary>
		/// <param name="i_ContactURIs">Array of ContactURIs</param>
		/// <param name="i_TimeToWaitInSeconds">Time to wait, in seconds, before aborting the search.</param>
		/// <returns>Array of Contacts, if successful.</returns>
		public GrooveWebServicesV12Helpers.Contact[] Fetch(string[] i_ContactURIs, int i_TimeToWaitInSeconds)
		{
			//  ---------------------------------------------------------------------------------------------
			//  BIG HONKING NOTE:  This method pumps messages while waiting for result from web service, thus
			//                     allowing for reentrancy.
			//  ---------------------------------------------------------------------------------------------

			//  Reset member variable
			m_FetchedContacts = null;

			//  Get initialized reference to web service
			GrooveContactsWebService.GrooveContacts ContactsWebService = GrooveWebServicesV12Helpers.Contact.CreateInitializedContactsWebService
				(
				m_Account.IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_CONTACTS_URI,
				m_Account.Context
				);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to fetch contacts
			string SubscriptionID = ContactsWebService.Fetch
				(
				GrooveWebServicesV12Helpers.EventManager.s_EventURI,
				DEFAULT_TIME_TO_LIVE_IN_HOURS,
				i_ContactURIs,
				this.ID
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("ContactsWebService::Fetch, " + TimeSpan.TotalMilliseconds + " ms");
			}

			//  Subscribe for the one event we should get back
			GrooveWebServicesV12Helpers.EventManager.AddEventListener
				(
				m_Account.Context,
				m_Account.IdentityURL,
				GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_CONTACT_DIRECTORY_EVENT_CLASS,
				"",		// Source URI
				GrooveWebServicesV12Helpers.EventManager.s_EventURI,
				SubscriptionID,
				1,		// 1 hour time to live
				this
				);

			//  Set flag
			m_WaitingForEvent = true;

			try
			{
				BeginDateTime = System.DateTime.Now.AddSeconds(i_TimeToWaitInSeconds);
				while (m_WaitingForEvent && (BeginDateTime > System.DateTime.Now))
				{
					System.Windows.Forms.Application.DoEvents();
					System.Threading.Thread.Sleep(100);
				}

				//  Reset flag
				m_WaitingForEvent = false;
			}
			finally
			{
				//  Unsubscribe for events
				GrooveWebServicesV12Helpers.EventManager.RemoveEventListener
					(
					SubscriptionID,
					this
					);
			}

			return m_FetchedContacts;
		}

		#endregion
	
		#region IGrooveWebServicesEventCallback Members

		public void ProcessEvent(GrooveEventsWebService.Event i_Event)
		{
			switch (i_Event.EventType)
			{
				case GrooveWebServicesV12Helpers.Shared.GROOVE_CONTACT_DIRECTORY_FETCH_RESULTS_EVENT_TYPE:
				{
					System.Collections.ArrayList ContactArrayList = new System.Collections.ArrayList();

					GrooveEventsWebService.GrooveContactFetchResultsEventData ContactFetchResultsEventData = (GrooveEventsWebService.GrooveContactFetchResultsEventData)i_Event.EventData;

					//  Populate array list of Contacts
					foreach (GrooveContactsWebService.Contact Contact in ContactFetchResultsEventData.ContactList)
					{
						GrooveWebServicesV12Helpers.Contact NewContact = new GrooveWebServicesV12Helpers.Contact 
							(
							m_Account,
							Contact
							);

						ContactArrayList.Add(NewContact);
					}

					//  Create array from array list
					if (ContactArrayList.Count > 0)
						m_FetchedContacts = (GrooveWebServicesV12Helpers.Contact[])ContactArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.Contact));

					break;
				}

				case GrooveWebServicesV12Helpers.Shared.GROOVE_CONTACT_DIRECTORY_SEARCH_RESULTS_EVENT_TYPE:
				{
					System.Collections.ArrayList ContactSummaryArrayList = new System.Collections.ArrayList();

					GrooveEventsWebService.GrooveContactSearchResultsEventData ContactSearchResultsEventData = (GrooveEventsWebService.GrooveContactSearchResultsEventData)i_Event.EventData;

                    if (ContactSearchResultsEventData.ContactSummaryList != null)
                    {
                        //  Populate array list of ContactSummaries
                        foreach (GrooveEventsWebService.ContactSummary ContactSummary in ContactSearchResultsEventData.ContactSummaryList)
                        {
                            GrooveWebServicesV12Helpers.ContactSummary NewContactSummary = new GrooveWebServicesV12Helpers.ContactSummary(ContactSummary);
                            ContactSummaryArrayList.Add(NewContactSummary);
                        }
                    }

					//  Create array from array list
					if (ContactSummaryArrayList.Count > 0)
						m_SearchedContactSummaries = (GrooveWebServicesV12Helpers.ContactSummary[])ContactSummaryArrayList.ToArray(typeof(GrooveWebServicesV12Helpers.ContactSummary));

					break;
				}

				default:
				{
					System.Diagnostics.Debug.WriteLine("[CalendarTool]Unknown event type: " + i_Event.EventType);
					break;
				}
			}

			//  Reset flag
			m_WaitingForEvent = false;
		}

		#endregion
	}
}
